#include "precompiled.h"
#include "bwlistdialog.h"
using namespace std;
using namespace weo::engine::item;
using namespace weo::ui;
std::set<unsigned int> BWListDialog::s_Whitelist;
std::set<unsigned int> BWListDialog::s_Blacklist;
QValidator::State BWListValidator::validate ( QString & input, int & pos ) const
{
    std::vector<std::string>::const_iterator it;
    std::string svalue = input.toStdString();
    boost::to_lower(svalue);
    unsigned int startval = m_StartChar[svalue[0]];
    bool previouslyfound = false;
    for(it = m_Values.begin()+startval; it != m_Values.end(); it++)
    {
        std::string value = *it;
        boost::to_lower(value);
        if(value.find(svalue) != 0) continue;
        else if(previouslyfound)
        {
            return QValidator::Invalid; // next char no fitting found
        }
        else
        {
            previouslyfound = true;
            m_Index = it-m_Values.begin();
            if(value != input.toStdString())
            {
                return QValidator::Intermediate;
            }
            else return QValidator::Acceptable;
            break;
        }
    }
    return QValidator::Invalid;
}
void BWListValidator::setValues(const std::vector<std::string>& values)
{
    m_Values = values;
    std::vector<std::string>::const_iterator it;
    for(it = m_Values.begin(); it != m_Values.end(); it++)
    {
        unsigned char keychar = std::tolower(it->at(0));
        if(m_StartChar[keychar] > 0) continue;
        else
        {
            m_StartChar[keychar] = it - m_Values.begin();
        }
    }
}
BWListDialog::BWListDialog(QWidget* parent /*= 0*/, Qt::WFlags flags /*= 0*/) : QDialog(parent, flags)
{
    setupUi(this);
    m_SearchValidator = new BWListValidator();
}
void BWListDialog::on_SearchLineEdit_textEdited( const QString & text)
{
    ItemsList->setCurrentRow(m_SearchValidator->Index());
}
void BWListDialog::setItems(const std::vector<std::vector<const weo::engine::item::Item*>>& items)
{
    m_AllItemsMap = Itemdatabase::getInstance()->getAllItemsMap();
    std::vector<std::vector<const weo::engine::item::Item*>>::const_iterator it;
    std::vector<const weo::engine::item::Item*>::const_iterator it2;
    for(it = items.begin(); it != items.end(); it++)
    {
        for(it2 = it->begin(); it2 != it->end(); it2++)
        {
            const Item *item = *it2;
            m_ItemsMap[item->Id()] = true;
            m_AllItemsMap[item->Id()] = true;
        }
    }
    std::set<unsigned int>::const_iterator it3;
    for(it3 = s_Whitelist.begin(); it3 != s_Whitelist.end();it3++)
    {
        m_ItemsMap.erase(*it3);
        m_AllItemsMap[*it3] = false;
    }
    for(it3 = s_Blacklist.begin(); it3 != s_Blacklist.end();it3++)
    {
        m_ItemsMap[*it3] = true;
        m_AllItemsMap[*it3] = true;
    }
    setupList();
}
void BWListDialog::on_ItemsList_itemDoubleClicked ( QListWidgetItem * item )
{
    unsigned int itemid = m_ItemIdMap[item];
    if(m_AllItemsMap[itemid] && s_Blacklist.count(itemid) == 0 && s_Whitelist.count(itemid) == 0) // light green auto whitelisted
    {
        s_Blacklist.insert(itemid);
        item->setForeground(QBrush(Qt::darkRed));
    }
    else if(s_Blacklist.count(itemid) > 0) // manually blacklisted unlist now
    {
        s_Blacklist.erase(itemid);
        if(!m_AllItemsMap[itemid])
        {
            item->setForeground(QBrush(Qt::darkGreen)); // manually whitelist
        }
        else
        {
            item->setForeground(QBrush(Qt::green)); // autowhitelist
        }
    }
    else if(s_Whitelist.count(itemid) > 0) // manually whitelist unlist now
    {
        s_Whitelist.erase(itemid);
        if(m_AllItemsMap[itemid])
        {
            item->setForeground(QBrush(Qt::darkRed)); // manually backlist
        }
        else
        {
            item->setForeground(QBrush(Qt::red)); // autoblacklist
        }
    }
    else // manually whitelist now
    {
        s_Whitelist.insert(itemid);
        item->setForeground(QBrush(Qt::darkGreen));
    }
}
void BWListDialog::setupList()
{
    std::vector<std::string> strings;
    std::map<unsigned int, bool>::const_iterator it;
    for(it = m_AllItemsMap.begin();it != m_AllItemsMap.end();it++)
    {
        const Item *item = Itemdatabase::getInstance()->getPtrbyId(it->first);
        QListWidgetItem *witem = new QListWidgetItem(tr(item->Name().c_str()));
        if(s_Whitelist.count(it->first) > 0)
        {
            witem->setForeground(QBrush(Qt::darkGreen));
        }
        else if(s_Blacklist.count(it->first) > 0)
        {
            witem->setForeground(QBrush(Qt::darkRed));
        }
        else if(it->second)
        {
            witem->setForeground(QBrush(Qt::green));
        }
        else
        {
            witem->setForeground(QBrush(Qt::red));
        }
        ItemsList->addItem(witem);
        m_ItemIdMap[witem] = it->first;
        strings.push_back(item->Name());
    }
    std::sort(strings.begin(),strings.end());
    m_SearchValidator->setValues(strings);
    SearchLineEdit->setValidator(m_SearchValidator);
}
void BWListDialog::loadXmlBWlist()
{
    try
    {
        ticpp::Document doc( "BWlist" );
        doc.LoadFile("bwlist.xml");
        std::string lists[] = {"whitelist","blacklist"};
        std::set<unsigned int>* plistarray[] = {&s_Whitelist,&s_Blacklist};
        for(int i = 0;i<2;i++)
        {
            ticpp::Element *pParent = doc.FirstChildElement(lists[i].c_str(),true);
            if(pParent != NULL)
            {
                ticpp::Element *pElem = pParent->FirstChildElement("items", true);
                if(pElem != NULL)
                {
                    ticpp::Element *pChild = pElem->FirstChildElement("item",false);
                    int counter = 0;
                    while(pChild != NULL)
                    {
                        int itemid = boost::lexical_cast<int>(pChild->GetText(false));
                        plistarray[i]->insert(itemid);
                        pChild = pChild->NextSiblingElement("item",false);
                        counter++;
                    }
                }
            }
        }
    }
    catch( ticpp::Exception& ex )
    {
        s_Whitelist.clear();
        s_Blacklist.clear();
    }
}
void BWListDialog::saveXmlBWlist()
{
    try
    {
        ticpp::Document doc;  
        ticpp::Element* msg;
        ticpp::Element* msgs;
        ticpp::Declaration* decl;
        ticpp::Element* root;
        std::string lists[] = {"whitelist","blacklist"};
        std::set<unsigned int>* plistarray[] = {&s_Whitelist,&s_Blacklist};
        std::set<unsigned int>::const_iterator it;
        decl = new (UseGC) ticpp::Declaration( "1.0", "", "" );  
        doc.LinkEndChild( decl );
        for(int i = 0;i<2;i++)
        {
            root = new (UseGC) ticpp::Element( lists[i] );  
            doc.LinkEndChild( root );  
            msgs = new (UseGC) ticpp::Element( "items" );  
            root->LinkEndChild( msgs ); 
            for(it = plistarray[i]->begin(); it != plistarray[i]->end();it++)
            {
                msg = new (UseGC) ticpp::Element( "item", boost::lexical_cast<std::string>(*it));
                msgs->LinkEndChild( msg ); 
            }
        }
        doc.SaveFile("bwlist.xml");
    }
    catch( ticpp::Exception& ex )
    {
    }
}